(function(angular) {
	'use strict';
	angular.module("fs.waf").factory('arithService', [ '$filter', 'storageService', function($filter, storageService) {
		/*
		 * add computation
		 * @param support for multiple numbers, strings or objects
		 * @return string of number
		 */
		function add() {
			var data = "0";
			if (arguments.length > 0) {
				if (typeof(arguments[0]) == 'object') arguments[0] = arguments[0].value ? arguments[0].value : arguments[0];
				var v = new Big(arguments[0]);
				for (var i = 1; i< arguments.length; i++) {
					if (typeof(arguments[i]) == 'object') arguments[i] = arguments[i].value ? arguments[i].value : arguments[i];
					v = v.plus(new Big(arguments[i]));
				}
				data = v.toString();
			}
			return (data);
		}
		

		/*
		 * subtration computation
		 * @param support for multiple numbers, strings or objects
		 * @return string of number
		 */
		function sub() {
			var data = "0";
			if (arguments.length > 0) {
				if (typeof(arguments[0]) == 'object') arguments[0] = arguments[0].value ? arguments[0].value : arguments[0];
				var v = new Big(arguments[0]);
				for (var i = 1; i< arguments.length; i++) {
					if (typeof(arguments[i]) == 'object') arguments[i] = arguments[i].value ? arguments[i].value : arguments[i];
					v = v.minus(new Big(arguments[i]));
				}
				data = v.toString();
			}
			return (data);
		}

		/*
		 * multiplication computation
		 * @param support for multiple numbers, strings or objects
		 * @return string of number
		 */
		function mul() {
			var data = "0";
			if (arguments.length > 0) {
				if (typeof(arguments[0]) == 'object') arguments[0] = arguments[0].value ? arguments[0].value : arguments[0];
				var v = new Big(arguments[0]);
				for (var i = 1; i< arguments.length; i++) {
					if (typeof(arguments[i]) == 'object') arguments[i] = arguments[i].value ? arguments[i].value : arguments[i];
					v = v.times(new Big(arguments[i]));
				}
				data = v.toString();
			}
			return (data);
		}

		/*
		 * dividing computation
		 * @param support for multiple numbers, strings or objects
		 * @return string of number
		 */
		function div() {
			var data = "0";
			if (arguments.length > 0) {
				if (typeof(arguments[0]) == 'object') arguments[0] = arguments[0].value ? arguments[0].value : arguments[0];
				var v = new Big(arguments[0]);
				for (var i = 1; i< arguments.length; i++) {
					if (typeof(arguments[i]) == 'object') arguments[i] = arguments[i].value ? arguments[i].value : arguments[i];
					v = v.div(new Big(arguments[i]));
				}
				data = v.toString();
			}
			return (data);
		}

		/*
		 * mathematical computation
		 * @param num1 support numbers
		 * @param num2 support numbers
		 * @param type the operator: '+', '-', '*', '/'
		 * @return number
		 */
		function calc(num1, num2, type){
			if(type == '+') return (this.add(num1, num2));
			if(type == '-') return (this.sub(num1, num2));
			if(type == '*') return (this.mul(num1, num2));
			if(type == '/') return (this.div(num1, num2));
		}

		/**
		 * quickly compute the average of the number/string array and the return value is not accurate
		 * @param support for multiple numbers or multiple objects
		 * @return string of average
		 */
		function quickAverage() {
			if (arguments.length == 0) return NaN;
			var v = new Big(arguments[0]);
			for (var i = 1; i< arguments.length; i++) {
				v = v.plus(arguments[i]);
			}
			return v.div(arguments.length).toString();
		}

		/**
		 * Returns the maximum of this array of number
		 * @param support for multiple numbers
		 * @return maximum
		 */
		function max() {
			if (arguments.length == 0) return NaN;
			var max = new Big(Number.MIN_VALUE);
			for (var i = 0; i < arguments.length; i++) {
				if (max.lt(arguments[i])) {
					max = new Big(arguments[i]);
				}
			}
			return max.toString();
		}

		/**
		 * Returns the minimum of this array of number
		 * @param support for multiple numbers
		 * @return minimum
		 */
		function min() {
			if (arguments.length == 0) return NaN;
			var min = new Big(Number.MAX_VALUE);
			for (var i = 0; i < arguments.length; i++) {
				if (min.gt(arguments[i])) {
					min = new Big(arguments[i]);
				}
			}
			return min.toString();
		}

		/**
		 * Returns true only if num1 greater than num2
		 * @param num1, num2
		 * @return true only if num1 greater than num2
		 */
		function gt(num1, num2) {
			if (arguments.length != 2) throw new Error('incorrect arguments number!');
			var l = new Big(num1);
			var r = new Big(num2);
			return l.gt(r);
		}

		/**
		 * Returns true if num1 greater than num2 or num1 equals to num2 
		 * @param num1, num2
		 * @return true if num1 greater than num2 or num1 equals to num2
		 */
		function gte(num1, num2) {
			if (arguments.length != 2) throw new Error('incorrect arguments number!');
			var l = new Big(num1);
			var r = new Big(num2);
			return l.gte(r);
		}	

		/**
		 * Returns true only if num1 equal to num2
		 * @param num1, num2
		 * @return true only if num1 equal to num2
		 */
		function eq(num1, num2) {
			if (arguments.length != 2) throw new Error('incorrect arguments number!');
			var l = new Big(num1);
			var r = new Big(num2);
			return l.eq(r);
		}

		/**
		 * Returns true only if num1 less than num2
		 * @param num1, num2
		 * @return true only if num1 less than num2
		 */
		function lt(num1, num2) {
			if (arguments.length != 2) throw new Error('incorrect arguments number!');
			var l = new Big(num1);
			var r = new Big(num2);
			return l.lt(r);
		}

		/**
		 * Returns true if num1 less than num2 or num1 equals to num2
		 * @param num1, num2
		 * @return true if num1 less than num2 or num1 equals to num2
		 */
		function lte(num1, num2) {
			if (arguments.length != 2) throw new Error('incorrect arguments number!');
			var l = new Big(num1);
			var r = new Big(num2);
			return l.lte(r);
		}
		
		return {
			add : add,
			sub : sub,
			mul : mul,
			div : div,
			calc : calc,
			quickAverage : quickAverage,
			max : max,
			min : min,
			gt : gt,
			gte : gte,
			eq : eq,
			lt : lt,
			lte : lte
		};
	} ]);
})(angular);
